﻿assert(CartoLight, "CartoLight not found!")
local CartoLight = CartoLight
local revision = tonumber(string.sub("$Revision: 3 $", 12, -3))
if revision > CartoLight.revision then
	CartoLight.version = "r" .. revision
	CartoLight.revision = revision
	CartoLight.date = string.sub("$Date: 2010-12-12 00:00:00 +0000 (Sun, 12 Dec 2010) $", 8, 17)
end

local L = Rock("LibRockLocale-1.0"):GetTranslationNamespace("CartoLight-ZoneInfo")

local function trace(msg)
--	DEFAULT_CHAT_FRAME:AddMessage(msg)
end

L:AddTranslations("enUS", function() return {
	["Zone Info"] = true,
	["Module which on hovering over a zone, will show the levels of the zone, the instances in the zone, their levels, and the group size the instance is made for (e.g. 5-man, 40-man)."] = true,
	["Transports"] = true,
	["Instances"] = true,
	["%d-man"] = true,
	[" and "] = true,
	["Show Fishing Level"] = true,
	["Show required and current fishing level"] = true,
	["Show Battle Pet Levels"] = true,
	["Show min and max level of the zone's Battle Pets"] = true,
	["Show Transports"] = true,
	["Show long distance transports like boats, zeppelins and portals"] = true,
	["Show Instances"] = true,
	["Show a list of located instances in the zone"] = true,
} end)

L:AddTranslations("koKR", function() return {
	["Zone Info"] = "지역 정보",
	["Module which on hovering over a zone, will show the levels of the zone, the instances in the zone, their levels, and the group size the instance is made for (e.g. 5-man, 40-man)."] = "해당 지역에 위치한 인던 및 참여할 수 있는 인원(예. 5명, 40명)등을 표시합니다.",
	["Transports"] = "Transports",
	["Instances"] = "인스턴스",
	["%d-man"] = "%d명",
	[" and "] = " and ",
	["Show Fishing Level"] = true,
	["Show required and current fishing level"] = true,
	["Show Battle Pet Levels"] = true,
	["Show min and max level of the zone's Battle Pets"] = true,
	["Show Transports"] = true,
	["Show long distance transports like boats, zeppelins and portals"] = true,
	["Show Instances"] = true,
	["Show a list of located instances in the zone"] = true,
} end)

L:AddTranslations("deDE", function() return {
	["Zone Info"] = "Zoneninfo",
	["Module which on hovering over a zone, will show the levels of the zone, the instances in the zone, their levels, and the group size the instance is made for (e.g. 5-man, 40-man)."] = "Modul, das Euch zu jedem Gebiet die Stufe sowie vorhandene Instanzen mit deren Level und jeweiliger Begrenzung der Spielerzahl anzeigt.",
	["Transports"] = "Transports",
	["Instances"] = "Instanzen",
	["%d-man"] = "%d Spieler",
	[" and "] = " und ",
	["Show Fishing Level"] = true,
	["Show required and current fishing level"] = true,
	["Show Battle Pet Levels"] = true,
	["Show min and max level of the zone's Battle Pets"] = true,
	["Show Transports"] = true,
	["Show long distance transports like boats, zeppelins and portals"] = true,
	["Show Instances"] = true,
	["Show a list of located instances in the zone"] = true,
} end)

L:AddTranslations("frFR", function() return {
	["Zone Info"] = "Infos de zone",
	["Module which on hovering over a zone, will show the levels of the zone, the instances in the zone, their levels, and the group size the instance is made for (e.g. 5-man, 40-man)."] = "Module affichant au passage de la souris sur une zone : la fourchette de niveaux de la zone, les instances s'y trouvant, leurs niveaux, et le nombre de joueurs que l'instance peut accueillir (par ex. 5j, 40j).",
	["Transports"] = "Transports",
	--["Instances"] = true,
	["%d-man"] = "%dj",
	[" and "] = " et ",
	["Show Fishing Level"] = true,
	["Show required and current fishing level"] = true,
	["Show Battle Pet Levels"] = true,
	["Show min and max level of the zone's Battle Pets"] = true,
	["Show Transports"] = true,
	["Show long distance transports like boats, zeppelins and portals"] = true,
	["Show Instances"] = true,
	["Show a list of located instances in the zone"] = true,
} end)

L:AddTranslations("esES", function() return {
	["Zone Info"] = "Información de la Zona",
	["Module which on hovering over a zone, will show the levels of the zone, the instances in the zone, their levels, and the group size the instance is made for (e.g. 5-man, 40-man)."] = "Módulo que muestra los niveles e instancias de la zona y los niveles y número de hombres necesarios para las instancias (p.ej. 5-hombres, 40-hombres) cuando se pasa el cursor por encima.",
	["Transports"] = "Transports",
	["Instances"] = "Instancias",
	["%d-man"] = "%d-hombres",
	[" and "] = " y ",
	["Show Fishing Level"] = true,
	["Show required and current fishing level"] = true,
	["Show Battle Pet Levels"] = true,
	["Show min and max level of the zone's Battle Pets"] = true,
	["Show Transports"] = true,
	["Show long distance transports like boats, zeppelins and portals"] = true,
	["Show Instances"] = true,
	["Show a list of located instances in the zone"] = true,
} end)

L:AddTranslations("zhTW", function() return {
	["Zone Info"] = "地區資訊",
	["Module which on hovering over a zone, will show the levels of the zone, the instances in the zone, their levels, and the group size the instance is made for (e.g. 5-man, 40-man)."] = "顯示游標所在地區資訊的模組，在世界地圖上顯示此地區的適合等級，此地區的副本和副本的人數限制 (例如: 5人、40人)。",
	["Transports"] = "Transports",
	["Instances"] = "副本",
	["%d-man"] = "%d人",
	[" and "] = " and ",
	["Show Fishing Level"] = true,
	["Show required and current fishing level"] = true,
	["Show Battle Pet Levels"] = true,
	["Show min and max level of the zone's Battle Pets"] = true,
	["Show Transports"] = true,
	["Show long distance transports like boats, zeppelins and portals"] = true,
	["Show Instances"] = true,
	["Show a list of located instances in the zone"] = true,
} end)

L:AddTranslations("zhCN", function() return {
	["Zone Info"] = "区域信息",
	["Module which on hovering over a zone, will show the levels of the zone, the instances in the zone, their levels, and the group size the instance is made for (e.g. 5-man, 40-man)."] = "显示鼠标所指的区域信息, 在世界地图上显示该区域的适合等级，该区域的副本及副本人数限制（例如5人、40人）。",
	["Transports"] = "Transports",
	["Instances"] = "副本",
	["%d-man"] = "%d人",
	[" and "] = " and ",
	["Show Fishing Level"] = true,
	["Show required and current fishing level"] = true,
	["Show Battle Pet Levels"] = true,
	["Show min and max level of the zone's Battle Pets"] = true,
	["Show Transports"] = true,
	["Show long distance transports like boats, zeppelins and portals"] = true,
	["Show Instances"] = true,
	["Show a list of located instances in the zone"] = true,
} end)

-- Russian Translation by StingerSoft (Eritnull aka Шептун)
L:AddTranslations("ruRU", function() return {
	["Zone Info"] = "Инфо о Зонах",
	["Module which on hovering over a zone, will show the levels of the zone, the instances in the zone, their levels, and the group size the instance is made for (e.g. 5-man, 40-man)."] = "Модуль который при наводке курсора на зону отображает уровни зоны, подземелья, их уровни допуска, и максимальное число человек доступное в подземельях (пример: 5-чел, 40-чел)",
	["Transports"] = "Transports",
	["Instances"] = "Подземелья",
	["%d-man"] = "%d-чел",
	[" and "] = " и ",
	["Show Fishing Level"] = true,
	["Show required and current fishing level"] = true,
	["Show Battle Pet Levels"] = true,
	["Show min and max level of the zone's Battle Pets"] = true,
	["Show Transports"] = true,
	["Show long distance transports like boats, zeppelins and portals"] = true,
	["Show Instances"] = true,
	["Show a list of located instances in the zone"] = true,
} end)

local Tourist = Rock("LibTourist-3.0")

CartoLight_ZoneInfo = CartoLight:NewModule("ZoneInfo")
local CartoLight_ZoneInfo = CartoLight_ZoneInfo

function CartoLight_ZoneInfo:OnInitialize()
	CartoLight_ZoneInfo.db = CartoLight:AcquireDBNamespace("ZoneInfo")
	CartoLight:RegisterDefaults("ZoneInfo", 'profile', {
		showFishing = true,
		showBattlePets = true,
		showTransports = true,
		showInstances = true,
	})

	self.name = L["Zone Info"]
	self.title = L["Zone Info"]
	
	CartoLight.options.args.ZoneInfo = {
		name = L["Zone Info"],
		desc = L["Module which on hovering over a zone, will show the levels of the zone, the instances in the zone, their levels, and the group size the instance is made for (e.g. 5-man, 40-man)."],
		type = 'group',
		args = {
			toggle = {
				name = CartoLight.L["Enabled"],
				desc = CartoLight.L["Suspend/resume this module."],
				type = "toggle",
				order = -1,
				get = function() return CartoLight:IsModuleActive(self) end,
				set = function() CartoLight:ToggleModuleActive(self) end
			},
			showFishing = {
				name = L["Show Fishing Level"],
				desc = L["Show required and current fishing level"],
				type = "toggle",
				get = function() return CartoLight_ZoneInfo.db.profile.showFishing end,
				set = function() CartoLight_ZoneInfo.db.profile.showFishing = not CartoLight_ZoneInfo.db.profile.showFishing end,
			},
			showBattlePets = {
				name = L["Show Battle Pet Levels"],
				desc = L["Show min and max level of the zone's Battle Pets"],
				type = "toggle",
				get = function() return CartoLight_ZoneInfo.db.profile.showBattlePets end,
				set = function() CartoLight_ZoneInfo.db.profile.showBattlePets = not CartoLight_ZoneInfo.db.profile.showBattlePets end,
			},
			showTransports = {
				name = L["Show Transports"],
				desc = L["Show long distance transports like boats, zeppelins and portals"],
				type = "toggle",
				get = function() return CartoLight_ZoneInfo.db.profile.showTransports end,
				set = function() CartoLight_ZoneInfo.db.profile.showTransports = not CartoLight_ZoneInfo.db.profile.showTransports end,
			},
			showInstances = {
				name = L["Show Instances"],
				desc = L["Show a list of located instances in the zone"],
				type = "toggle",
				get = function() return CartoLight_ZoneInfo.db.profile.showInstances end,
				set = function() CartoLight_ZoneInfo.db.profile.showInstances = not CartoLight_ZoneInfo.db.profile.showInstances end,
			},
		},
		handler = self,
	}

end

function CartoLight_ZoneInfo:OnEnable()
	if not self.frame then
		self.frame = CreateFrame("Frame", "CartoLightZoneInfo", WorldMapFrame)
		self.frame.text = WorldMapFrameAreaFrame:CreateFontString(nil, "OVERLAY", "GameFontHighlightLarge")
		local text = self.frame.text
		local font, size = GameFontHighlightLarge:GetFont()
		text:SetFont(font, size, "OUTLINE")
		text:SetPoint("TOP", WorldMapFrameAreaDescription, "BOTTOM", 0, 0)
		text:SetWidth(1024)
	end
	self.frame:Show()
end

function CartoLight_ZoneInfo:OnDisable()
	self.frame:Hide()
	WorldMapFrameAreaLabel:SetTextColor(1, 1, 1)
end

-- Used by "debug stuff" below
local function GetCursorMapLocation(button)
	local x, y = GetCursorPosition()
	local left, top = button:GetLeft(), button:GetTop()
	local width = button:GetWidth()
	local height = button:GetHeight()
	local scale = button:GetEffectiveScale()

	return (x/scale - left) / width, (top - y/scale) / height
end

local lastDisplayedTopLine
local lastDisplayedZoneName
local lastRealZoneName
local lastZone
local useRealZoneName
local t = {}
local old_WorldMapButton_OnUpdate = WorldMapButton_OnUpdate
function WorldMapButton_OnUpdate(...)
	old_WorldMapButton_OnUpdate(...)
	local self = CartoLight_ZoneInfo
	if not CartoLight:IsModuleActive(self) then
		return
	end
	if not self.frame then
		return
	end
	if not WorldMapDetailFrame:IsShown() or not WorldMapFrameAreaLabel:IsShown() then
		self.frame.text:SetText("")
		lastZone = nil
		return
	end



	local underAttack = false
	local zone
	local zoneText = ""	
	local continentID = GetCurrentMapContinent()
	if WorldMapFrameAreaLabel:GetText() then
	
		if WorldMapFrameAreaDescription:GetText() then
			underAttack = true
			zoneText = WorldMapFrameAreaDescription:GetText()
		else
			zoneText = WorldMapFrameAreaLabel:GetText()
		end
		
		-- Remove color coding
		zoneText = string.gsub(zoneText, " |cff.+$", "")
		zoneText = string.gsub(zoneText, "|cff.+$", "") -- For Dreanor zones
		
		-- Remove realzonename
		local pos2 = string.find(zoneText, "%s%(")
		if (pos2) then
			zoneText = string.sub(zoneText, 1, pos2 - 1)
		end

		zone = Tourist:GetUniqueZoneNameForLookup(zoneText, continentID)
	end
	
	local worldMapFrameAreaName = WorldMapFrame.areaName
	-- Check if the top line has changed since ZoneInfo has set it
	if zone ~= lastDisplayedTopLine then
		local realZoneNameChanged = false
		
		-- Check if a real zone is displayed
		if not Tourist:IsZoneOrInstance(zone) then
			-- It's not, get the real zone name from WorldMapFrame.areaName
			-- See if it has changed since last update
			if worldMapFrameAreaName ~= lastRealZoneName then
				realZoneNameChanged = true
				-- Remember real zone name
				lastRealZoneName = worldMapFrameAreaName
			end
		else
			-- It's a real zone. Change in zone?
			if lastRealZoneName ~= zoneText then
				realZoneNameChanged = true
				-- Remember real zone name
				lastRealZoneName = zoneText
			end
		end
	
		if (zoneText ~= lastDisplayedZoneName) or realZoneNameChanged then
			-- The displayed zone name and/or the real zone name have changed
			if zoneText then
				-- Real zone name is to be displayed if zone and lastRealZoneName are not equal
				-- However, zone contains color coding as of patch 4.3 so a straight forward comparison did not work anymore
				-- Try to remove the color coding
				local equalZones = false
				local pos = string.find(zoneText, "|cff")
				if pos then
					zoneText = string.sub(zoneText, 1, pos -1 )
				end
			
				if lastRealZoneName then
					-- Compare length
					if string.len(zoneText) == string.len(lastRealZoneName) then
					-- and content
						equalZones = (string.find(lastRealZoneName, zoneText) == 1)
					end
					useRealZoneName = not equalZones
				else
					-- Don't use the real zone name if we don't have one
					useRealZoneName = false
				end
					
				-- Debugging
--				if useRealZoneName then
--					trace("Source zone update: "..tostring(zoneText).."; ".. tostring(lastRealZoneName))
--				else
--					trace("Source zone update: "..tostring(zoneText))
--				end
			end
			-- Remember displayed zone name
			lastDisplayedZoneName = zoneText
		end
	end
	
	if not zone or not Tourist:IsZoneOrInstance(zone) then
		-- Get the real zone name for functions like GetLevel and GetFactionColor
		zone = Tourist:GetUniqueZoneNameForLookup(worldMapFrameAreaName, continentID)
	end
	
	
--	debug stuff
--	if GetCurrentMapContinent() == 5 then
--		local x, y = GetCursorMapLocation(WorldMapDetailFrame)
--		local name, fileName, texPctX, texPctY, texX, texY, scrollX, scrollY = UpdateMapHighlight(x, y)
--		if name then
--			trace( tostring(zone)..": name = "..tostring(name)..", file = "..tostring(fileName).." texX = "..tostring(texX))
--		end
--	end
--	trace(tostring(GetCurrentMapAreaID()))
	
	
	WorldMapFrameAreaLabel:SetTextColor(1, 1, 1)
	WorldMapFrameAreaPetLevels:Hide()
	
	if zone and (Tourist:IsZoneOrInstance(zone) or Tourist:DoesZoneHaveInstances(zone)) then
		if not underAttack then
			WorldMapFrameAreaLabel:SetTextColor(Tourist:GetFactionColor(zone))
			WorldMapFrameAreaDescription:SetTextColor(1, 1, 1)
		else
			WorldMapFrameAreaLabel:SetTextColor(1, 1, 1)
			WorldMapFrameAreaDescription:SetTextColor(Tourist:GetFactionColor(zone))
		end
				
		local low, high = Tourist:GetLevel(zone)		
		if low > 0 and high > 0 then
			local levelText
			local r, g, b = Tourist:GetLevelColor(zone)
			if low == high then
				levelText = string.format(" |cff%02x%02x%02x[%d]|r", r * 255, g * 255, b * 255, high)
			else
				levelText = string.format(" |cff%02x%02x%02x[%d-%d]|r", r * 255, g * 255, b * 255, low, high)
			end
			
			local sizeText = ""
			local groupSize = Tourist:GetInstanceGroupSize(zone)
			if groupSize > 0 then
				sizeText = " " .. string.format(L["%d-man"], groupSize)
			end
	
			if useRealZoneName then
				lastDisplayedTopLine = zoneText..levelText..sizeText.." ("..lastRealZoneName..")"
			else
				lastDisplayedTopLine = zoneText..levelText..sizeText
			end
	
			-- Show combined text for first line
			if not underAttack then
				WorldMapFrameAreaLabel:SetText(lastDisplayedTopLine)
			else
				WorldMapFrameAreaDescription:SetText(lastDisplayedTopLine)
			end
		end
		
		if (WORLDMAP_SETTINGS.size == 1) then
			-- Show details only when map size is not reduced
			if lastZone ~= zone then
				lastZone = zone
				self.frame.text:SetText("")
				
				-- Determine Fishing level
				local minFish
				local fishing_skill_text
				if CartoLight_ZoneInfo.db.profile.showFishing then
					minFish = Tourist:GetFishingLevel(zone)
					if minFish == 0 then 
						-- no fishing in this zone
						minFish = nil
					end
					if minFish then
						-- Get all professions
						local prof_1, prof_2, archaeology, fishing, cooking, firstaid = GetProfessions()
						
						if fishing then
							-- Player has Fishing skill, get fishing info
							local name, icon, rank, maxrank, numspells, spelloffset, skillline = GetProfessionInfo(fishing) 
							local fishingSpell = GetSpellInfo(7620) -- 7620 Fishing
							if not fishingSpell then fishingSpell = "Fishing" end
							local r,g,b = 1,1,0
							local r1,g1,b1 = 1,0,0
														
							if minFish <= rank then
								-- Green
								r1,g1,b1 = 0,1,0
							else
								-- Get skill precentage
								local skillPct = (rank/minFish) * 100
								if skillPct < 50 then
									-- Red
									r1,g1,b1 = 1,0,0
								elseif skillPct < 75 then
									-- Orange
									r1,g1,b1 = 1, 0.7, 0
								else
									-- Yellow
									r1,g1,b1 = 1, 1, 0
								end
							end
							fishing_skill_text = string.format("|cff%02x%02x%02x%s|r |cff%02x%02x%02x[%d] (%d)|r",r * 255, g * 255, b * 255,fishingSpell, r1 * 255, g1 * 255, b1 * 255, minFish, rank)
						end

						if not fishing_skill_text then
							minFish = nil
						end
					end
				end
				
				-- Determine transport connections
				local transports = {}
				local hasTransports
				if CartoLight_ZoneInfo.db.profile.showTransports then
					for path in Tourist:IterateBorderZones(zone, false) do
						if not Tourist:IsZoneOrInstance(path) then
							transports[path] = true
							hasTransports = true
						end
					end
				end
				
				local hasInstances = Tourist:DoesZoneHaveInstances(zone) and CartoLight_ZoneInfo.db.profile.showInstances
				local noTable = false
				
				-- Add Battle Pet level
				local hasBattlePets = false

				if CartoLight_ZoneInfo.db.profile.showBattlePets then
					local bpLow, bpHigh = Tourist:GetBattlePetLevel(zone)
					hasBattlePets = (bpLow and bpHigh)
					if hasBattlePets then
						local bpLevelString = Tourist:GetBattlePetLevelString(zone)
						local bp_level_text = string.format("|cff%02x%02x%02xBattle Pets: [%s]|r", 255, 255, 0, bpLevelString)
						if hasTransports or hasInstances or (minFish and fishing_skill_text) then
							table.insert(t,bp_level_text)
							if not minFish and not fishing_skill_text and (hasTransports or hasInstances) then
								table.insert(t,"")
							end
						else
							-- Battle Pets only: show one line (no table)
							self.frame.text:SetText(bp_level_text)
							noTable = true
						end
					end
				end
				
				-- Add fishing level
				if minFish and fishing_skill_text then
					if hasTransports or hasInstances or hasBattlePets then
						table.insert(t,fishing_skill_text)
						if hasTransports or hasInstances then
							table.insert(t,"")
						end
					else
						-- Fishing only: show one line (no table)
						self.frame.text:SetText(fishing_skill_text)
						noTable = true
					end
				end
				
				-- Add transport connections
				if hasTransports then
					local r, g, b
					table.insert(t, string.format("|cffffff00%s:|r", L["Transports"]))
					for k, v in pairs(transports) do
						r, g, b = Tourist:GetFactionColor(k)
						table.insert(t, string.format("|cff%02x%02x%02x%s|r", r * 255, g * 255, b * 255, k))
					end
					if hasInstances then
						table.insert(t,"")
					end
				end
									
				-- Add instances
				if hasInstances then
					table.insert(t, string.format("|cffffff00%s:|r", L["Instances"]))
					for instance in Tourist:IterateZoneInstances(zone) do
						local complex = nil
						if not Tourist:IsComplex(zone) then
							complex = Tourist:GetComplex(instance)
						end
						local low, high = Tourist:GetLevel(instance)
						local r1, g1, b1 = Tourist:GetFactionColor(instance)
						local r2, g2, b2 = Tourist:GetLevelColor(instance)
						local groupSize = Tourist:GetInstanceGroupSize(instance)
						local altGroupSize = Tourist:GetInstanceAltGroupSize(instance)
						local name = instance
						if complex then
							name = complex .. " - " .. instance
						end
						if Tourist:IsBattleground(instance) then
							name = "BG: " .. name
						elseif Tourist:IsArena(instance) then
							name = "A: " .. name
						end						
						if low == high then
							if (altGroupSize > 0) and (groupSize > 0) then
								table.insert(t, string.format("|cff%02x%02x%02x%s|r |cff%02x%02x%02x[%d]|r " .. L["%d-man"] .. L[" and "] .. L["%d-man"], r1 * 255, g1 * 255, b1 * 255, name, r2 * 255, g2 * 255, b2 * 255, high, groupSize, altGroupSize))
							elseif groupSize > 0 then
								table.insert(t, string.format("|cff%02x%02x%02x%s|r |cff%02x%02x%02x[%d]|r " .. L["%d-man"], r1 * 255, g1 * 255, b1 * 255, name, r2 * 255, g2 * 255, b2 * 255, high, groupSize))
							else
								table.insert(t, string.format("|cff%02x%02x%02x%s|r |cff%02x%02x%02x[%d]|r", r1 * 255, g1 * 255, b1 * 255, name, r2 * 255, g2 * 255, b2 * 255, high))
							end
						else
							if (altGroupSize > 0) and (groupSize > 0) then
								table.insert(t, string.format("|cff%02x%02x%02x%s|r |cff%02x%02x%02x[%d-%d]|r " .. L["%d-man"] .. L[" and "] .. L["%d-man"], r1 * 255, g1 * 255, b1 * 255, name, r2 * 255, g2 * 255, b2 * 255, low, high, groupSize, altGroupSize))
							elseif groupSize > 0 then
								table.insert(t, string.format("|cff%02x%02x%02x%s|r |cff%02x%02x%02x[%d-%d]|r " .. L["%d-man"], r1 * 255, g1 * 255, b1 * 255, name, r2 * 255, g2 * 255, b2 * 255, low, high, groupSize))
							else
								table.insert(t, string.format("|cff%02x%02x%02x%s|r |cff%02x%02x%02x[%d-%d]|r", r1 * 255, g1 * 255, b1 * 255, name, r2 * 255, g2 * 255, b2 * 255, low, high))
							end
						end
					end
				end
				
				-- Show result (if table)
				if noTable == false then
					self.frame.text:SetText(table.concat(t, "\n"))
					for k in pairs(t) do
						t[k] = nil
					end
				end				
			end
		end		
	elseif not zone then
		lastZone = nil
		self.frame.text:SetText("")
	end
end


